import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import {
    Tooltip,
    TooltipContent,
    TooltipProvider,
    TooltipTrigger,
} from "@/components/ui/tooltip"

import MethodCombobox, { ComboboxItem } from "@/components/methodcombobox";
import { useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import { atom, useAtom, useAtomValue } from 'jotai'
import { atomWithStorage } from "jotai/utils";
import { CheckIcon, ClipboardCopyIcon, CopyIcon, ExternalLinkIcon, GlobeIcon, PaperPlaneIcon, ReloadIcon, TrashIcon } from "@radix-ui/react-icons"
import { toast } from "sonner";
import { CommandSelection } from "@/components/commandselect";
import { buildUrl, cn, tryParseJSON } from "@/lib/utils";
import { object, z } from "zod";
import { useTranslation, Trans } from 'react-i18next';

import 'react-json-view-lite/dist/index.css';
import { OpenInBrowser } from "../../wailsjs/go/main/App";
import i18next from "i18next";
import { StyleProps } from "react-json-view-lite/dist/DataRenderer";
import Indicator from "@/components/indicator-icon";
import { ScrollArea } from "@/components/ui/scroll-area";
import JsonViewer from "@/components/json-viewer";
import { useAsyncValue } from "react-router-dom";
import { LogDebug } from "../../wailsjs/runtime/runtime";

let items: ComboboxItem[] = [
    { value: "get", label: "GET" },
    { value: "post", label: "POST" },
]

const deviceIp = "device_ip"

const methodAtom = atom<'get' | 'post'>('post')
const jsonCommandAtom = atom<string>('')
const readWriteJsonCommandAtom = atom(
    (get) => get(jsonCommandAtom),
    (_, set, newValue: string) => {
        set(jsonCommandAtom, newValue)
        set(resAtom, null)

        var cmd = tryParseJSON(newValue)
        if (cmd && cmd.cmd === "upload person" && cmd.reg_image) {
            LogDebug('update face image')
            var imgData = 'data:img/jpg;base64,' + cmd.reg_image
            set(faceImgBase64Atom, imgData)
        }

    })
const jsonValidateMsgAtom = atom((get) => {
    const json = get(jsonCommandAtom)
    const method = get(methodAtom)
    if (method == 'get') {
        return ''
    } else {
        if (!json) {
            return "cmd-empty"
        } else {
            return tryParseJSON(json) ? "" : "invalid-json"
        }
    }
})


const selectedCommandObjectAtom = atom((get) => {
    const jsonValidateMsg = get(jsonValidateMsgAtom)
    const json = get(jsonCommandAtom)
    if (jsonValidateMsg) {
        return {}
    }
    return JSON.parse(json)
}

)

//selected cmd, only the cmd part
const selectedCommandNameAtom = atom((get) => {
    const commandObject = get(selectedCommandObjectAtom)
    return commandObject.cmd ?? ""
})
const deviceUrlAtom = atomWithStorage(deviceIp, '')
//response json result
const resAtom = atom(null)
const sendBtnDisableAtom = atom((get) => {
    const method = get(methodAtom);
    const url = get(deviceUrlAtom);
    const jsonCmd = get(jsonCommandAtom)
    const jsonValidateMsg = get(jsonValidateMsgAtom)
    if (method === 'get') {
        return !url
    } else {
        return !url || !jsonCmd || !!jsonValidateMsg
    }
})

const faceImgBase64Atom = atom<string | null>("")

const isUploadPersonCmdAtom = atom<boolean>((get) => {
    const cmd = get(selectedCommandObjectAtom)
    return cmd.cmd === "upload person" && cmd.reg_image
})


function openInExtBrowser() {

}


export default function () {
    const [method, setMethod] = useAtom(methodAtom)
    const [res, setRes] = useAtom(resAtom)
    const [urlOrIp, setUrl] = useAtom(deviceUrlAtom)
    const [cmd, setCmd] = useAtom(readWriteJsonCommandAtom)
    const [sendButtonDisabled] = useAtom(sendBtnDisableAtom)
    const [busy, setBusy] = useState(false)
    const [jsonValidateMsg] = useAtom(jsonValidateMsgAtom)
    const [selCommand] = useAtom(selectedCommandNameAtom)
    const isUploadPersonCmd = useAtomValue(isUploadPersonCmdAtom)
    const [faceImgBase64, setFaceImgBase64] = useAtom(faceImgBase64Atom)
    const fileInputRef = useRef<HTMLInputElement>(null)
    const { t } = useTranslation()

    console.log(isUploadPersonCmd)

    async function sendCommand() {
        setRes(null)
        setBusy(true)
        let url = buildUrl(urlOrIp, false);

        try {
            let resp = await fetch(url, {
                method,
                body: cmd
            })
            await new Promise(resolve => setTimeout(resolve, 250));
            let res = await resp.json()
            setRes(res)
        } catch (error) {
            LogDebug(JSON.stringify(error, null, 2))
            toast((error as any).message)
        } finally {
            setBusy(false)
        }

    }



    async function openInBrowser() {
        const url = buildUrl(urlOrIp, true)

        await OpenInBrowser(url, [])
    }

    async function copyToClipboard() {
        await navigator.clipboard.writeText(JSON.stringify(res, null, 2))
        //toast.success(t('copySucceed'))
    }


    return (
        <div className="flex flex-col h-full gap-4">
            <div className="flex flex-row items-center gap-x-4">
                <MethodCombobox items={items} selectedValue={method} onSelect={(v) => setMethod(v as 'get' | 'post')} />
                <Label className="flex items-center gap-2 ">IP/URL:
                    <TooltipProvider>
                        <Tooltip delayDuration={0}>
                            <TooltipTrigger asChild>
                                <Input className="flex-1 inline-block w-96"
                                    value={urlOrIp}
                                    onInput={v => setUrl(v.currentTarget.value)}
                                    placeholder={t('url-input-placeholder')} />
                            </TooltipTrigger>
                            <TooltipContent>
                                <p>{t('url-input-tip')}</p>
                            </TooltipContent>
                        </Tooltip>
                    </TooltipProvider>
                </Label>
                <Button
                    disabled={sendButtonDisabled || busy}
                    className=""
                    onClick={sendCommand}>
                    {busy ?
                        <ReloadIcon className={cn("mr-2 h-4 w-4", { "animate-spin": busy })} /> :
                        <PaperPlaneIcon className={cn("mr-2 h-4 w-4", { "animate-spin": busy })} />}
                    {t('send-command')}
                </Button>
                <Button
                    disabled={!urlOrIp}
                    className="mr-auto"
                    onClick={openInBrowser}>
                    {t('open')}
                    <ExternalLinkIcon className="w-4 h-4 ml-2" />
                </Button>



            </div>
            <div className="flex-1 grid grid-cols-2 grid-rows-[auto_1fr] gap-2 overflow-y-auto">
                <div className="flex items-center gap-4 capitalize">
                    <CommandSelection placeHolder={t('select-command')} onSelectCmd={cmd => {
                        setCmd(JSON.stringify(cmd, null, 2))
                    }} />
                    {selCommand}
                </div>
                <div className="flex items-center">
                    <Label> {t('response')}</Label>
                    <Button variant="link" size="icon" className="h-auto">
                        <Indicator normal={<CopyIcon />} indicator={<CheckIcon />} delay={1000} onClick={copyToClipboard} />
                    </Button>
                </div>
                <div className="relative flex flex-col gap-2">
                    <Textarea className="flex-1 resize-none focus-visible:ring-0"
                        disabled={method == 'get'}
                        //aria-errormessage={jsonValidateMsg}
                        value={cmd}
                        onInput={v => {
                            setCmd(v.currentTarget.value)
                        }}>
                    </Textarea>
                    {jsonValidateMsg && <p className="absolute px-1 text-sm text-red-600 rounded-tl left-px top-px bg-background">{t(jsonValidateMsg)}</p>}
                    {isUploadPersonCmd &&
                        <div className="flex flex-col items-center gap-1.5 absolute top-px right-px bg-background p-2">
                            <TooltipProvider>
                                <Tooltip delayDuration={0}>
                                    <TooltipTrigger>
                                        <Input
                                            type="file"
                                            className="hidden w-auto"
                                            accept="image/png, image/jpeg"
                                            ref={fileInputRef}
                                            onChange={() => {
                                                const file = fileInputRef.current?.files?.[0]
                                                if (file) {
                                                    const reader = new FileReader();
                                                    reader.onload = () => {
                                                        const base64 = reader.result as string
                                                        setFaceImgBase64(base64)
                                                        const json = JSON.parse(cmd)
                                                        const noHeader = base64.split(',')[1];
                                                        json.reg_image = noHeader
                                                        setCmd(JSON.stringify(json, null, 2))
                                                    }
                                                    reader.readAsDataURL(file);
                                                }
                                            }} />
                                        <Button
                                            variant="secondary"
                                            onClick={() => {
                                                console.log("handle click")
                                                fileInputRef.current?.click();
                                            }}>
                                            {t('selectImage')}
                                        </Button>
                                    </TooltipTrigger>
                                    <TooltipContent>
                                        <p>{t('imageSelectorToolTip')}</p>
                                    </TooltipContent>
                                </Tooltip>

                            </TooltipProvider>

                            {
                                faceImgBase64 &&
                                <div className="relative group">
                                    <img
                                        alt="face image"
                                        src={faceImgBase64}
                                        className="object-cover w-32 h-32"
                                    />
                                    <div className="absolute top-0 bottom-0 left-0 right-0 flex flex-col items-center justify-center invisible group-hover:visible bg-black/70 ">
                                        <Button variant="destructive" size="icon" onClick={() => {
                                            setFaceImgBase64(null);
                                            fileInputRef.current!.value = "";
                                        }}>
                                            <TrashIcon className="w-4 h-4" />
                                        </Button>
                                    </div>
                                </div>
                            }
                        </div>}
                </div>
                <ScrollArea className="border rounded">
                    {res && <JsonViewer data={res} />}
                </ScrollArea>
            </div>
        </div>
    )
}


